#ifndef _CU_INT1_H_
#define _CU_INT1_H_

//**********************************************************************************
// int1 operators and functions
//**********************************************************************************

SDH_CALL int1 operator + (const int1 & u, int v) { int1 r = { u.x + v }; return r; }
SDH_CALL int1 operator - (const int1 & u, int v) { int1 r = { u.x - v }; return r; }
SDH_CALL int1 operator * (const int1 & u, int v) { int1 r = { u.x * v }; return r; }
SDH_CALL int1 operator / (const int1 & u, int v) { int1 r = { u.x / v }; return r; }

SDH_CALL int1 operator + (int v, const int1 & u) { int1 r = { v + u.x }; return r; }
SDH_CALL int1 operator - (int v, const int1 & u) { int1 r = { v - u.x }; return r; }
SDH_CALL int1 operator * (int v, const int1 & u) { int1 r = { v * u.x }; return r; }
SDH_CALL int1 operator / (int v, const int1 & u) { int1 r = { v / u.x }; return r; }

SDH_CALL int1 operator + (const int1 & u, const int1 & v) { int1 r = { u.x + v.x }; return r; }
SDH_CALL int1 operator - (const int1 & u, const int1 & v) { int1 r = { u.x - v.x }; return r; }
SDH_CALL int1 operator * (const int1 & u, const int1 & v) { int1 r = { u.x * v.x }; return r; }
SDH_CALL int1 operator / (const int1 & u, const int1 & v) { int1 r = { u.x / v.x }; return r; }

SDH_CALL int1   operator - (const int1 & v) { int1 r = { -v.x }; return r; }

SDH_CALL int1 & operator += (int1 & u, const int1 & v) { u.x += v.x; return u; }
SDH_CALL int1 & operator -= (int1 & u, const int1 & v) { u.x -= v.x; return u; }
SDH_CALL int1 & operator *= (int1 & u, const int1 & v) { u.x *= v.x; return u; }
SDH_CALL int1 & operator /= (int1 & u, const int1 & v) { u.x /= v.x; return u; }

SDH_CALL int1 & operator += (int1 & u, int v) { u.x += v; return u; }
SDH_CALL int1 & operator -= (int1 & u, int v) { u.x -= v; return u; }
SDH_CALL int1 & operator *= (int1 & u, int v) { u.x *= v; return u; }
SDH_CALL int1 & operator /= (int1 & u, int v) { u.x /= v; return u; }

SDH_CALL int1 catmullrom (const int1 & P0, const int1 & P1, const int1 & P2, const int1 & P3, float t)
{
  const float ts = t * t;
  const float tc = t * ts;

  return (P0 * (-tc + 2.0f * ts - t) + P1 * (3.0f * tc - 5.0f * ts + 2.0f) + P2 * (-3.0f * tc + 4.0f * ts + t) + P3 * ( tc - ts)) * 0.5f;
}
SDH_CALL int1 lerp      (const int1 & u, const int1 & v, float t ) { return u + t * (v - u); }
SDH_CALL int  dot       (const int1 & u, const int1 & v) { return (u.x*v.x); }
SDH_CALL int1 clamp     (const int1 & u, int a, int b) { int1 r = { clamp(u.x, a, b) }; return r; }

SDH_CALL int1 saturate  (const int1 & u) { return clamp(u, 0.0f, 1.0f); }

SDH_CALL int1 min(const int1 & u, const int1 & v){ int1 r = {min(u.x, v.x)}; return r; }
SDH_CALL int1 max(const int1 & u, const int1 & v){ int1 r = {max(u.x, v.x)}; return r; }

SDH_CALL int    sad (const int1 & u, const int1 & v) { return (abs(u.x - v.x)); } // Sum of Absolute Differences for x components
SDH_CALL int    ssd (const int1 & u, const int1 & v) { return (sqr(u.x - v.x)); } // Sum of Squared Differences for x components

SDH_CALL float  length (const int1 & u) { return abs(u.x); }

#endif